package com.framework.loippi.plugins.wxapppay.refund;

import com.framework.loippi.cache.ConfigCache;
import com.framework.loippi.plugins.wxapppay.MD5;
import com.framework.loippi.plugins.wxapppay.MD5Util;
import com.framework.loippi.plugins.wxapppay.WXpayConfig;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;

import javax.net.ssl.SSLContext;
import java.io.*;
import java.security.KeyStore;
import java.util.*;

public class WechatMobileRefund {

    private static final Logger logger = LoggerFactory.getLogger(WechatMobileRefund.class);

    /**
     * @param out_trade_no
     * @param total_fee
     * @Author: WQY
     * @Description:微信退款
     * @Date: 2017-9-11 14:35
     * @return:
     */
    public static String wxPayRefund(String out_trade_no, String total_fee, String refund_fee, String type) {

        String appId = "";
        String mchId = "";
        String partnerKey = "";

        switch (type) {
            case "2":
                appId = ConfigCache.getConfig("wx.mp.appId");//WXpayConfig.PUBLIC_APP_ID;
                mchId = ConfigCache.getConfig("wx.mp.pay.partnerId");
                partnerKey = ConfigCache.getConfig("wx.mp.pay.partnerKey");
                break;
            case "3":
                appId = ConfigCache.getConfig("wx.ma.appId");//WXpayConfig.MINI_APP_ID;
                mchId = ConfigCache.getConfig("wx.ma.pay.partnerId");
                partnerKey = ConfigCache.getConfig("wx.ma.pay.partnerKey");
                break;
            case "1":
            default:
                appId = ConfigCache.getConfig("wx.open.appId");//WXpayConfig.APP_ID;
                mchId = ConfigCache.getConfig("wx.open.pay.partnerId");
                partnerKey = ConfigCache.getConfig("wx.open.pay.partnerKey");
                break;
        }

        StringBuffer xml = new StringBuffer();
        String data = null;
        try {
            String nonceStr = genNonceStr();
            xml.append("</xml>");
            SortedMap<String, String> parameters = new TreeMap<String, String>();
            parameters.put("appid", appId);
            parameters.put("mch_id", mchId);//);
            parameters.put("nonce_str", nonceStr);
            parameters.put("out_trade_no", out_trade_no);
            //parameters.put("transaction_id", transaction_id);
            parameters.put("out_refund_no", nonceStr);
            parameters.put("fee_type", "CNY");
            parameters.put("total_fee", total_fee);
            parameters.put("refund_fee", refund_fee);
            parameters.put("op_user_id", mchId);//TODO
            parameters.put("sign", createSign(parameters, partnerKey));
            data = SortedMaptoXml(parameters);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            return null;
        }
        return data;
    }

    /**
     * 证书使用
     * 微信退款
     */
    @SuppressWarnings("deprecation")
    public static String wxPayBack(String url, String data) throws Exception {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");

        StringBuffer pkcsPath = new StringBuffer();
        pkcsPath.append("classpath:").append(ConfigCache.getConfig("wx.open.pay.ssl.pkcs12File"));
        logger.debug("证书所在路径： " + pkcsPath.toString());
        InputStream instream = null;
        String sslPassword = ConfigCache.getConfig("wx.open.pay.ssl.password");

        try {
            instream = ResourceUtils.getURL(pkcsPath.toString()).openStream();
        } catch (IOException var10) {
        }

        if (instream == null) {
            logger.warn("证书文件没找到：" +pkcsPath.toString());
            return null;
        }

        String result = "";
        try {
            keyStore.load(instream, sslPassword.toCharArray());
        } finally {
            instream.close();
        }

        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, sslPassword.toCharArray())
                .build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                new String[]{"TLSv1"},
                null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();
        try {
            HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
            StringEntity entitys = new StringEntity(data);
            httppost.setEntity((HttpEntity) entitys);
            CloseableHttpResponse response = httpclient.execute(httppost);
            try {
                HttpEntity entity = response.getEntity();

                if (entity != null) {
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
                    String text = "";
                    String t = "";
                    while ((text = bufferedReader.readLine()) != null) {
                        t += text;
                    }
                    byte[] temp = t.getBytes("gbk");//这里写原编码方式
                    String newStr = new String(temp, "utf-8");//这里写转换后的编码方式
                    result = newStr;
                }
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
        return result;
    }

    /**
     * @param params
     * @Author: WQY
     * @Description:请求值转换为xml格式 SortedMap转xml
     * @Date: 2017-9-7 17:18
     */
    private static String SortedMaptoXml(SortedMap<String, String> params) {
        StringBuilder sb = new StringBuilder();
        Set es = params.entrySet();
        Iterator it = es.iterator();
        sb.append("<xml>\n");
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            sb.append("<" + k + ">");
            sb.append(v);
            sb.append("</" + k + ">\n");
        }
        sb.append("</xml>");
        return sb.toString();
    }

    /**
     * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
     */
    public static String createSign(SortedMap<String, String> packageParams, String AppKey) {
        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + AppKey);
        String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
        return sign;
    }

    /**
     * 生成32位随机数字
     */
    public static String genNonceStr() {
        Random random = new Random();
        return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
    }

//	public static void main(String[] args) {
//		WeiRefund weiRefund = new WeiRefund();
//		weiRefund.setOutrefundno("2019072919114818");//退款单号
//		weiRefund.setOuttradeno("2019072919114818");
//		weiRefund.setTotalfee(new BigDecimal("0.01").multiply(new BigDecimal(100)).intValue());//总金额
//		weiRefund.setRefundfee(new BigDecimal("0.01").multiply(new BigDecimal(100)).intValue());//退款金额
//		Map<String, Object> map = WechatMobileRefund.toRefund(weiRefund);
//		System.out.println(map);
//	}
}
